package com.black.opencvStudy;

import org.junit.Test;
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.util.ArrayList;
import java.util.List;

/**
 * @description：
 * 图像的基本操作
 * @author：8568
 */
public class Demo4 extends OpencvEV{

    /**
     * 访问和修改像素
    */
    @Test
    public void readChangePx() {
        Mat backGround = new Mat(new Size(2, 2), CvType.CV_8UC3, new Scalar(1,2,3));
        // 获取单个坐标的像素
        double[] doubles = backGround.get(1, 1);
        byte[] data = new byte[backGround.cols() * backGround.rows() *  3];
        // 获取指定坐标到最后一个坐标的像素
        backGround.get(0, 0, data);
        
        // 修改坐标类似

        // 访问图像的通道类型
        int type = backGround.type();
    }
    
    /**
     * 图像感兴趣的区域
    */
    @Test
    public void roi1() {
        Mat img = Imgcodecs.imread("src/main/resources/img/img.jpg", Imgcodecs.IMREAD_COLOR);
        HighGui.namedWindow("win1", HighGui.WINDOW_AUTOSIZE);
        // 绘制感兴趣的区域
        Imgproc.rectangle(img,
                new Point(400,400),
                new Point(800,800),
                new Scalar(0,0.,255));
        HighGui.imshow("win1", img);
        HighGui.waitKey(0);
        img.release();
    }

    /**
     * 以坐标轴方式 截取 矩形(实际相当关于原图的区域引用)
     * 依次给定 X、Y、width、weight （x,y）开始点位置 (width, height) 宽高
     * 注意： 坐标原点为图片左上角、width的正方向向右、height的正方向向下
     */
    @Test
    public void roi2() {
        Mat img = Imgcodecs.imread("src/main/resources/img/img.jpg", Imgcodecs.IMREAD_COLOR);
        Mat submat = img.submat(new Rect(400, 400, 400, 400));
        showImg(submat);
    }

    /**
     * 用图片在原始图片上划定 ROI 区域，并替换(如添加 logo)
     */
    @Test
    public void roi3() {
        // 读取logo
        Mat logo = new Mat(new Size(40, 40), CvType.CV_8UC3, new Scalar(0, 0, 255));
        Mat img = Imgcodecs.imread("src/main/resources/img/img.jpg", Imgcodecs.IMREAD_COLOR);
        // 读取logo的宽高
        int cols = logo.cols();
        int rows = logo.rows();
        // 在原图上划定感兴趣的区域
        Mat submat = img.submat(new Rect(400 - cols, 400 - rows, cols, rows));
        // 合并图像前判断两个图片的通道是否一致、不一致需要转换
        if (img.channels() != submat.channels()) {
            Imgproc.cvtColor(img, logo, Imgproc.COLOR_GRAY2BGR);
        }
        //第一第四个参数就是各自权重
        Core.addWeighted(submat, 0.1, logo, 0.9, 0., submat);
        //
        showImg(img);
    }

    /**
     * 用图片在原始图片上划定 ROI 区域，并替换(如添加 logo)
     */
    @Test
    public void roi4() {
        // 读取logo
        Mat logo = new Mat(new Size(40, 40), CvType.CV_8UC3, new Scalar(0, 0, 255));
        Mat img = Imgcodecs.imread("src/main/resources/img/img.jpg", Imgcodecs.IMREAD_COLOR);
        // 读取logo的宽高
        int cols = logo.cols();
        int rows = logo.rows();
        // 在原图上划定感兴趣的区域
        Mat submat = img.submat(new Rect(0, 0, cols, rows));
        // 把logo移动到感兴趣的区域上
        logo.copyTo(submat);
        //
        showImg(img);
    }


    /**
     *  拆分和合并通道
    */
    @Test
    public void channelOp1() {
        Mat img = Imgcodecs.imread("src/main/resources/img/img.jpg", Imgcodecs.IMREAD_COLOR);
        // 获取每个通道
        List<Mat> mats = new ArrayList<>();
        Core.split(img, mats);
        HighGui.namedWindow("window");
        // 分别是BGR
        mats.forEach(m -> {
            HighGui.imshow("window", m);
            HighGui.waitKey(0);
        });
        // 合并图像
        Mat merged = new Mat();
        Core.merge(mats, merged);
        HighGui.imshow("window", merged);
        HighGui.waitKey(0);
    }

    private void showImg(Mat img) {
        HighGui.namedWindow("win1", HighGui.WINDOW_AUTOSIZE);
        HighGui.imshow("win1", img);
        HighGui.waitKey(0);
        img.release();
    }

}
